import { ModelFrom, CommentColorLevel, PropertyDataType, PropertyKey } from "@/constants/Enums";
import { modelService } from "@/modules/model/service";
import { DealTermRes, ModelValue, NeedSplitTerm, OriginTextInfo, PropertyRow, TermInfo, PropertyRowGroup } from "../types";
import { PaneModel } from "./PaneModel";
import { MetaclassType } from "@/constants/MetaclassType";
import { coworkService } from "@/modules/cowork/service/CoworkService";
import { CommentPropertyMapParam2 } from "@/modules/cowork/service/dto";
import { toRaw } from "vue";
import { archService } from "@/modules/model/service/ArchService";
import { SlotsInPropertyPane } from "@/modules/model/service/archServiceDto";
import { cloneDeep } from "lodash-es";
import { propertyUtil } from "@/modules/model/comps/station/sider/attribute/PropertyUtil";

function generateRowId(belongModelId, key) {
  return belongModelId + "_" + key;
}

export class PropertyPaneModel extends PaneModel {
  loading = false;

  // tableData:PropertyRow[]=[];
  tableDataGroups: PropertyRowGroup[] = [];
  loaded = false;
  loadedComment = false; // 是否加载了批注

  activeRowId?: string;
  classifierSlotsData: SlotsInPropertyPane[] = [];

  async loadTable() {
    const { projectId, modelId, modelIds } = this.tabsModel.data;

    if (!projectId || (!modelId && (!modelIds || !modelIds.length))) {
      // this.tableData = [];
      this.tableDataGroups = [];
      return;
    }
    const level = app.global.attributeShowLevel;
    if (modelIds && modelIds.length) {
      this.loading = true;
      const res = await modelService.getModelsProperties(projectId, modelIds!, level).finally(() => (this.loading = false));
      this.tableDataGroups = [{ properties: res, key: "", name: "", model: this.tabsModel.data.modelData!, expand: true }];
    } else {
      // const res1 = await modelService.getModelProperties(projectId, modelId!, level).finally(() => this.loading = false);

      const res = await modelService.getModelPropertiesV2(projectId, modelId!, level).finally(() => (this.loading = false));
      this.tableDataGroups = res;

      if (this.tableDataGroups[0].properties) {
        this.tableDataGroups[0].properties.push({
          dataType: PropertyDataType.STRING,
          displayLevel: 1,
          displayName: "唯一标识",
          enName: "uid",
          enTips: "Element Unique Identifier.",
          isMultiplicity: false,
          key: "uid",
          instanceId: modelId,
          id_: generateRowId(modelId, "uid"),
          modelId: modelId,
          name: "uid",
          nullable: true,
          readonly: true,
          items: null,
          tips: "元素唯一标识",
          value: modelId
        } as any);
      }

      this.tableDataGroups.forEach(group => {
        group.expand = true;
        group.properties.forEach(it => {
          it.id_ = generateRowId(group?.model?.id, it.key);
          // 事件类型属性特殊处理， 如果没有instanceId,需要传transitionId,通过row.extraData传递到属性编辑组件里
          if (it.key === PropertyKey.Trigger_eventType && !it.instanceId) {
            it.extraData = it.extraData || {};
            it.extraData.transitionId = modelId;
          }

          // 有可能一开始没有modelId，这里需要重新赋值
          if (this.activeRowId && this.activeRowId?.indexOf("undefined") > -1 && this.activeRowId?.indexOf(it.key) > -1) {
            this.activeRowId = it.id_;
          }
        });
      });
      // this.tableData = res;
      this.loaded = true;

      // 记录属性值，进行术语切割记录到对应属性值当中
      this.dealTermPropertyValue(projectId, this.tableDataGroups);
      // 加载批注
      await this.loadTableComment();
      return this.tableDataGroups;
    }
  }
  /**
   * 获取批注
   * */
  async loadTableComment() {
    // 是否是协同项目 || 是否显示批注 || 属性是否加载过
    if (!this.tabsModel.project?.config.online || !this.tabsModel.project.ui.isShowComment || !this.loaded) return;
    this.loadedComment = true;
    let { id, onlineConfig } = this.tabsModel.project.config;
    let modelIds: string[] = [];
    this.tableDataGroups.forEach(it => {
      if (it.instanceId) modelIds.push(it.instanceId);
    });
    const params: CommentPropertyMapParam2 = {
      projectId: id,
      projectVersion: onlineConfig.version,
      modelIds,
      isSolved: this.tabsModel.project.commentModel?.data.isSolved,
      commentVersionIds: toRaw(this.tabsModel.project.commentModel?.data.commentVersionIds),
      approvalNumbers: toRaw(this.tabsModel.project?.commentModel?.data.approvalNumbers)
    };
    const res = await coworkService.commentPropertyMap(params);

    // 批注数据 追加
    // const list = this.tableDataGroups[0]?.properties;
    // if (!list) return;

    // list.forEach(item => {
    //   if (res[item.key]) {
    //     item.commentList = res[item.key];
    //     // 是否有未解决
    //     const isSolved = item.commentList.some(v => !v.isSolved);
    //     if (isSolved) {
    //       item.priorityCommentLevel = item.commentList.reduce((prev, cur) => {
    //         if (cur.isSolved) return prev;
    //         return prev > cur.priorityLevel ? prev : cur.priorityLevel;
    //       }, 0);
    //     } else {
    //       item.priorityCommentLevel = CommentColorLevel.SOLVED;
    //     }
    //   } else {
    //     item.commentList = [];
    //     item.priorityCommentLevel = undefined;
    //   }
    // });

    this.tableDataGroups.forEach(item => {
      const modelId = item.instanceId;

      if (modelId && item.properties && item.properties.length) {
        item.properties.forEach(property => {
          if (res[property.key]) {
            property.commentList = res[property.key]?.filter(it => it.modelId === modelId);

            // 是否有未解决
            if (property.commentList?.length) {
              const isSolved = property.commentList.some(v => !v.isSolved);
              if (isSolved) {
                property.priorityCommentLevel = property.commentList.reduce((prev, cur) => {
                  if (cur.isSolved) return prev;
                  return prev > cur.priorityLevel ? prev : cur.priorityLevel;
                }, 0);
              } else {
                property.priorityCommentLevel = CommentColorLevel.SOLVED;
              }
            }
          } else {
            property.commentList = [];
            property.priorityCommentLevel = undefined;
          }
        });
      }
    });
  }

  async dealTermPropertyValue(projectId: string, groups: PropertyRowGroup[]) {
    const needSplitTermList: NeedSplitTerm[] = [];

    for (const group of groups) {
      const list = group.properties;

      list.forEach(item => {
        if (item.dataType === PropertyDataType.STRING) {
          if (item.value && typeof item.value === "string") {
            needSplitTermList.push({
              modelId: item.instanceId || "",
              propertyKey: item.key,
              originText: item.value as string
            });
          }
        } else if (item.dataType === PropertyDataType.INSTANCE) {
          if (item.value) {
            if (item.valueSpecificationInfo) {
              if (item.valueSpecificationInfo.metaclass === MetaclassType.LiteralString) {
                if (item.valueSpecificationInfo.value) {
                  needSplitTermList.push({
                    modelId: item.instanceId || "",
                    propertyKey: item.key,
                    originText: [
                      {
                        modelId: item.modelId,
                        originText: item.valueSpecificationInfo.value
                      }
                    ]
                  });
                }
              }
            }
            if (Array.isArray(item.value)) {
              const termInfoList: OriginTextInfo[] = [];
              item.value.forEach(val => {
                if (val?.id && val.name) {
                  termInfoList.push({
                    modelId: val.id,
                    originText: val.name
                  });
                }
              });
              needSplitTermList.push({
                modelId: item.instanceId || "",
                propertyKey: item.key,
                originText: termInfoList
              });
            } else {
              let _value = item.value as ModelValue;
              if (_value?.id && _value?.name) {
                needSplitTermList.push({
                  modelId: item.instanceId || "",
                  propertyKey: item.key,
                  originText: [
                    {
                      modelId: _value.id,
                      originText: _value.name
                    }
                  ]
                });
              }
            }
          }
        }
      });
    }

    const termRes: DealTermRes[] = await modelService.dealTermPropertyValue(
      projectId,
      needSplitTermList.filter(pro => pro.originText.length)
    );
    if (termRes.length === 0) return;
    const termInfoMap = new Map<string, DealTermRes>();
    termRes.forEach(it => {
      termInfoMap.set(it.modelId + it.propertyKey, it);
    });
    for (const group of groups) {
      const list = group.properties;
      for (const property of list) {
        const _term = termInfoMap.get(property.modelId + property.key);
        if (!_term) {
          continue;
        }
        if (Array.isArray(_term.terms) && _term.terms.length && property.value && _term.terms[0].hasOwnProperty("modelId")) {
          for (let info of _term.terms) {
            if (property.valueSpecificationInfo) {
              property.valueSpecificationInfo.terms = (info as TermInfo).terms;
            } else if (Array.isArray(property.value)) {
              const _value = (property.value as ModelValue[]).find(
                pro => (pro as ModelValue).id === (info as TermInfo).modelId
              ) as ModelValue;
              _value.terms = (info as TermInfo)?.terms;
            } else {
              // value是对象
              (property.value as ModelValue).terms = (info as TermInfo)?.terms;
            }
          }
        } else {
          property.terms = _term.terms as string[];
        }
      }
    }
  }

  async loadClassifierSlots() {
    // const { projectId, modelId } = this.tabsModel.data;
    // if (!projectId || !modelId) {
    //   this.classifierSlotsData = [];
    //   return;
    // }
    // this.classifierSlotsData = await archService.querySlotsInPropertyPane(projectId, modelId);
    // this.classifierSlotsData.forEach(it => {
    //   it.id_ = generateRowId();
    //   it.children.forEach(i => {
    //     i.id_ = generateRowId();
    //   });
    // });
  }

  getVisibleTableDataGroups(): PropertyRowGroup[] {
    return this.tableDataGroups.map(group => {
      return {
        ...group,
        properties: this.getVisibleTableData(group.properties)
      };
    });
  }
  getVisibleTableData(tableData?: PropertyRow[]) {
    // const groups = this.tableDataGroups
    // let tableData = this.tableData;
    tableData = tableData ? tableData : this.tableDataGroups[0]?.properties;
    const { showLevel, sortByNameActive, searchQuery, modelData, filterCommentActive } = this.tabsModel.data;
    let result = tableData?.filter(it => it?.displayLevel <= showLevel);
    if (searchQuery) {
      const lowerSearchQuery = searchQuery.toLowerCase();

      result = result.filter(it => {
        const oldName = it?.displayName!.toLowerCase() || "";
        return oldName.includes(lowerSearchQuery);
      });
    }

    if (sortByNameActive) {
      result.sort((i, j) => {
        return i.displayName!.localeCompare(j?.displayName || "");
      });
    }
    if (modelData) {
      if (modelData.from != ModelFrom.USER_CREATE) {
        result.forEach(item => (item.readonly = true));
      }
    }
    if (filterCommentActive) {
      result = result.filter(item => (item.priorityCommentLevel ?? -1) > -1);
    }

    const newTableList = cloneDeep(result);
    let renameObj = newTableList.find(item => item.key === "87691457310863808");
    if (renameObj) {
      let renameObjIndex = newTableList.findIndex(item => item.key === "87691457310863808");
      const renameProperty = ((renameObj.value || []) as string[]).filter(item => item !== null && item !== undefined && item !== "");
      const renameArr = renameProperty.map(item => JSON.parse(item));
      if (renameArr.length === 0) {
        return newTableList;
      }
      newTableList[renameObjIndex].value = renameArr.map(item => {
        let propertyName = propertyUtil.getTranslatedPropertyName(item.propertyKey, item.name || "");
        return `${item.reNameColumnName}(${propertyName})`;
      });
    }
    return newTableList;
  }
  async loadDataWhenNotLoad() {
    if (!this.loaded) {
      await this.loadTable();
      // await this.loadClassifierSlots();
    } else if (!this.loadedComment) {
      await this.loadTableComment();
    }
  }
  async fresh() {
    this.loadTable();
    // this.loadClassifierSlots();
  }

  async clear() {
    this.tableDataGroups = [];
    this.loaded = false;
  }
}
